const _ = require("lodash");

const S1 = require("./select32NumbersByS1.js");
const S2 = require("./select32NumbersByS2.js");
const S3 = require("./select32NumbersByS3.js");
const S4 = require("./select32NumbersByS4.js");

const strategyWindowMap = {
  S1: 40,
  S2: 60,
  S3: 20,
  S4: 60,
};

const strategyPool = { S1, S2, S3, S4 };
const historyMap = {};
const MAX_HISTORY = 30;
const MAX_ALLOWED_WRONG = 3;
const COOLDOWN_ROUNDS = 10;

// ✅ 全局轮数缓存，避免重复执行
let lastExecutedRound = -1;

/**
 * 🎯 V11：防止多次重复执行同一轮 + 不跳过 temp 太短
 */
function select32NumbersByS11(temp) {
  const currentRound = temp.length;
  const actualPrev = temp[temp.length - 1]?.number;
  if (!actualPrev) return [];

  // ✅ 防止重复执行同一轮（重要！）
  if (currentRound === lastExecutedRound) {
    return []; // 已执行过这轮，直接跳过
  }
  lastExecutedRound = currentRound;

  const voteMap = {};

  Object.entries(strategyPool).forEach(([name, fn]) => {
    const winSize = strategyWindowMap[name];
    const subTemp = temp.length >= winSize ? temp.slice(-winSize) : temp;

    if (subTemp.length < 5) return;

    const key = `${name}-${winSize}`;
    if (!historyMap[key]) {
      historyMap[key] = {
        history: [],
        cooldownUntilRound: 0,
        lastRound: 0,
      };
    }

    const record = historyMap[key];

    if (record.cooldownUntilRound && currentRound < record.cooldownUntilRound) return;
    if (record.lastRound === currentRound) return;
    record.lastRound = currentRound;

    const predicted = fn(subTemp);
    if (!predicted || predicted.length === 0) return;

    const hit = predicted.includes(actualPrev) ? 1 : 0;
    record.history.push(hit);
    if (record.history.length > MAX_HISTORY) record.history.shift();

    const maxWrong = calcMaxWrongStreak(record.history);
    if (maxWrong >= MAX_ALLOWED_WRONG) {
      record.cooldownUntilRound = currentRound + COOLDOWN_ROUNDS;
      return;
    }

    const weight = _.mean(record.history);
    predicted.forEach((num) => {
      voteMap[num] = (voteMap[num] || 0) + weight;
    });
  });

  const result = Object.entries(voteMap)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 32)
    .map(([n]) => n);

  console.log(`[S11][Round ${currentRound}] voted: ${result.length}`);
  return result;
}

function calcMaxWrongStreak(arr) {
  let max = 0, curr = 0;
  for (const v of arr) {
    if (v === 0) {
      curr++;
      max = Math.max(max, curr);
    } else {
      curr = 0;
    }
  }
  return max;
}

module.exports = select32NumbersByS11;
